package cc.linker.steplink.crm.task;

import cc.linker.steplink.crm.commons.enums.IntegralEnums;
import cc.linker.steplink.crm.commons.integral.IntegralRequest;
import cc.linker.steplink.crm.commons.lock.RedisLock;
import cc.linker.steplink.crm.commons.utils.CalendarUtils;
import cc.linker.steplink.crm.dao.ArticleDataDao;
import cc.linker.steplink.crm.dao.CustomerBindDao;
import cc.linker.steplink.crm.dao.ScoreActDao;
import cc.linker.steplink.crm.dao.SyncContentDao;
import cc.linker.steplink.crm.domain.*;
import cc.linker.steplink.crm.merchant.dao.WxDao;
import cc.linker.steplink.crm.merchanth5.dao.ScoreActiveCacheDao;
import cc.linker.steplink.crm.merchanth5.dao.VipCustomerLogDao;
import cc.linker.steplink.crm.merchanth5.service.CustomerIntegralService;
import cc.linker.steplink.crm.merchanth5.service.redis.ScoreActiveCacheService;
import com.alibaba.fastjson.JSON;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 积分活动
 */
@Slf4j
@Component
public class ScoreActivityTask {
    @Autowired
    private CustomerBindDao customerBindDao;
    @Autowired
    private ArticleDataDao articleDataDao;
    @Autowired
    private ScoreActDao scoreActDao;
    @Autowired
    private CustomerIntegralService customerIntegralService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private ScoreActiveCacheService scoreActiveCacheService;
    @Autowired
    private ScoreActiveCacheDao scoreActiveCacheDao;
    @Autowired
    private VipCustomerLogDao vipCustomerLogDao;
    @Autowired
    private WxDao wxDao;
    @Autowired
    private SyncContentDao syncContentDao;

    private static final String ARTICLE_BEHAVIOR = "article_behavior_";

    @Async
    public void execute(String day) {
//        doScoreTask();
        invokeScore();
        invokeCache(day);
        invokeShareDeal(day);
        invokeShare(day);
    }

    @Async
    @RedisLock("ScoreActivityTask")
    @Scheduled(cron = "0 30 2 * * *")
    public void execute() {
//        doScoreTask();
        invokeScore();
        invokeCache(null);
        invokeShareDeal(null);
        invokeShare(null);
    }


    //分享成交
    private void invokeShareDeal(String day) {
        SimpleDateFormat format = new SimpleDateFormat(CalendarUtils.DAY_FORMAT);
        String yesterday;
        if (!StringUtils.isEmpty(day)) {
            yesterday = day;
        } else {
            yesterday = format.format(CalendarUtils.getYesterdayDefault());
        }
        String orderNumKey = scoreActiveCacheService.shareKey+"deal_" + yesterday + "_*";
        Set<String> keys = stringRedisTemplate.keys(orderNumKey);
        if (null != keys && keys.size() > 0) {
            for (String key : keys) {
                String s = stringRedisTemplate.opsForValue().get(key);
                if (!StringUtils.isEmpty(s)) {
                    int orderNum = Integer.valueOf(s);
                    if (orderNum < 1) {
                        continue;
                    }
                    String[] sp = key.split("_");
                    String orgId = sp[3];
                    String customerId = sp[4];
                    String type = sp[5];//growth--score
                    String st;
                    if ("growth".equals(type)) {
                        st = "2";
                    } else {
                        st = "1";
                    }
                    List<Map<String, Object>> saList = scoreActDao.getScoreActList(orgId, st,"deal");
                    if (null != saList && saList.size() > 0) {
                        for (Map<String, Object> sa : saList) {
                            Map<String, Object> rule = (Map<String, Object>) JSON.parse(sa.get("rule").toString());
                            int v = Integer.valueOf(rule.get("val1").toString());
                            int score = Integer.valueOf(rule.get("val2").toString());
                            if (orderNum >= v) {
                                Integer allScore = (orderNum / v) * score;
                                int reduce = v;
                                if(v>0){
                                    reduce = orderNum-(orderNum%v);
                                }
                                String integralFieldName;
                                int sendWx = 0;
                                if ("1".equals(sa.get("type").toString())) {
                                    //积分
                                    integralFieldName = IntegralEnums.customerScore.toString();
                                    sendWx = 1;
                                } else {
                                    //成长值
                                    integralFieldName = IntegralEnums.customerGrowthScore.toString();
                                    sendWx = 2;
                                }
                                LOGGER.info("<-----cacheOrderNum3deal----->" + key);
                                this.customerIntegralService.addIntegralCustomerLog(customerId, "分享成交赠送", integralFieldName, allScore.toString(), IntegralEnums.mallSystem.toString(), orgId);

                                if (1 == sendWx) {
                                    Map<String, Object> logParam = new HashMap<>();
                                    logParam.put("scoreLogId", UUID.randomUUID().toString());
                                    logParam.put("customerId", customerId);
                                    logParam.put("scoreValue", allScore);
                                    logParam.put("scoreType", 9);
                                    logParam.put("actionRemark", "分享成交赠送" + allScore + "积分");
                                    logParam.put("sendWx", sendWx);
                                    scoreActiveCacheDao.addLog(logParam);
                                }
                                if (2 == sendWx) {
                                    Map<String, Object> log = new HashMap<String, Object>();
                                    log.put("logId", UUID.randomUUID().toString());
                                    log.put("customerId", customerId);
                                    log.put("growthValue", allScore);
                                    log.put("growthType", 9);
                                    log.put("actionRemark", "分享成交赠送" + allScore + "成长值");
                                    vipCustomerLogDao.addGrowth(log);
                                }
                                stringRedisTemplate.opsForValue().decrement(key, (long)reduce);
//                                stringRedisTemplate.delete(key);
                            }
                        }
                    }
                }
            }
        }
    }
    private void invokeShare(String day) {
        SimpleDateFormat format = new SimpleDateFormat(CalendarUtils.DAY_FORMAT);
        String yesterday;
        if (!StringUtils.isEmpty(day)) {
            yesterday = day;
        } else {
            yesterday = format.format(CalendarUtils.getYesterdayDefault());
        }
        String orderNumKey = scoreActiveCacheService.shareKey + yesterday + "_*";
        Set<String> keys = stringRedisTemplate.keys(orderNumKey);
        if (null != keys && keys.size() > 0) {
            for (String key : keys) {
                String s = stringRedisTemplate.opsForValue().get(key);
                if (!StringUtils.isEmpty(s)) {
                    int orderNum = Integer.valueOf(s);
                    if (orderNum < 1) {
                        continue;
                    }
                    String[] sp = key.split("_");
                    String activeType = sp[2];//open subscribe register
                    String orgId = sp[3];
                    String customerId = sp[4];
                    String type = sp[5];//growth--score
                    String st;
                    if ("growth".equals(type)) {
                        st = "2";
                    } else {
                        st = "1";
                    }
                    String activeTypeStr = "";
                    int scoreType = 0;
                    switch (activeType){
                        case "open":
                            activeTypeStr = "分享传播赠送";
                            scoreType = 12;
                            break;
                        case "subscribe":
                            activeTypeStr = "分享关注公众号赠送";
                            scoreType = 11;
                            break;
                        case "register":
                            activeTypeStr = "邀请注册赠送";
                            scoreType = 10;
                            break;
                            default:break;
                    }
                    List<Map<String, Object>> saList = scoreActDao.getScoreActList(orgId, st,activeType);
                    if (null != saList && saList.size() > 0) {
                        for (Map<String, Object> sa : saList) {
                            Map<String, Object> rule = (Map<String, Object>) JSON.parse(sa.get("rule").toString());
                            int v = Integer.valueOf(rule.get("val1").toString());
                            int score = Integer.valueOf(rule.get("val2").toString());
                            if (orderNum >= v) {
                                Integer allScore = (orderNum / v) * score;
                                int reduce = v;
                                if(v>0){
                                    reduce = orderNum-(orderNum%v);
                                }
                                String integralFieldName;
                                int sendWx = 0;
                                if ("1".equals(sa.get("type").toString())) {
                                    //积分
                                    integralFieldName = IntegralEnums.customerScore.toString();
                                    sendWx = 1;
                                } else {
                                    //成长值
                                    integralFieldName = IntegralEnums.customerGrowthScore.toString();
                                    sendWx = 2;
                                }
                                LOGGER.info("<-----cacheOrderNum3----->" + key);
                                this.customerIntegralService.addIntegralCustomerLog(customerId, activeTypeStr, integralFieldName, allScore.toString(), IntegralEnums.mallSystem.toString(), orgId);

                                if (1 == sendWx) {
                                    Map<String, Object> logParam = new HashMap<>();
                                    logParam.put("scoreLogId", UUID.randomUUID().toString());
                                    logParam.put("customerId", customerId);
                                    logParam.put("scoreValue", allScore);
                                    logParam.put("scoreType", scoreType);
                                    logParam.put("actionRemark", activeTypeStr + allScore + "积分");
                                    logParam.put("sendWx", sendWx);
                                    scoreActiveCacheDao.addLog(logParam);
                                }
                                if (2 == sendWx) {
                                    Map<String, Object> log = new HashMap<String, Object>();
                                    log.put("logId", UUID.randomUUID().toString());
                                    log.put("customerId", customerId);
                                    log.put("growthValue", allScore);
                                    log.put("growthType", scoreType);
                                    log.put("actionRemark", activeTypeStr + allScore + "成长值");
                                    vipCustomerLogDao.addGrowth(log);
                                }
                                stringRedisTemplate.opsForValue().decrement(key, (long)reduce);
//                                stringRedisTemplate.delete(key);
                            }
                        }
                    }
                }
            }
        }
    }
    private void invokeCache(String day) {
        SimpleDateFormat format = new SimpleDateFormat(CalendarUtils.DAY_FORMAT);
        String yesterday;
        if (!StringUtils.isEmpty(day)) {
            yesterday = day;
        } else {
            yesterday = format.format(CalendarUtils.getYesterdayDefault());
        }
        String orderNumKey = scoreActiveCacheService.orderNumKey + yesterday + "_*";
        Set<String> keys = stringRedisTemplate.keys(orderNumKey);
        if (null != keys && keys.size() > 0) {
            for (String key : keys) {
                String s = stringRedisTemplate.opsForValue().get(key);
                if (!StringUtils.isEmpty(s)) {
                    int orderNum = Integer.valueOf(s);
                    if (orderNum < 1) {
                        continue;
                    }
                    String[] sp = key.split("_");
                    String orgId = sp[2];
                    String customerId = sp[3];
                    String type = sp[4];//growth--score
                    String st;
                    if ("growth".equals(type)) {
                        st = "2";
                    } else {
                        st = "1";
                    }
                    List<Map<String, Object>> saList = scoreActDao.getScoreActList(orgId, st,"order");
                    if (null != saList && saList.size() > 0) {
                        for (Map<String, Object> sa : saList) {
                            Map<String, Object> rule = (Map<String, Object>) JSON.parse(sa.get("rule").toString());
                            int v = Integer.valueOf(rule.get("val1").toString());
                            int score = Integer.valueOf(rule.get("val2").toString());
                            if (orderNum >= v) {
                                Integer allScore = (orderNum / v) * score;
                                int reduce = v;
                                if(v>0){
                                    reduce = orderNum-(orderNum%v);
                                }
                                String integralFieldName;
                                int sendWx = 0;
                                if ("1".equals(sa.get("type").toString())) {
                                    //积分
                                    integralFieldName = IntegralEnums.customerScore.toString();
                                    sendWx = 1;
                                } else {
                                    //成长值
                                    integralFieldName = IntegralEnums.customerGrowthScore.toString();
                                    sendWx = 2;
                                }
                                LOGGER.info("<-----cacheOrderNum3----->" + key);
                                this.customerIntegralService.addIntegralCustomerLog(customerId, "完成下单赠送", integralFieldName, allScore.toString(), IntegralEnums.mallSystem.toString(), orgId);

                                if (1 == sendWx) {
                                    Map<String, Object> logParam = new HashMap<>();
                                    logParam.put("scoreLogId", UUID.randomUUID().toString());
                                    logParam.put("customerId", customerId);
                                    logParam.put("scoreValue", allScore);
                                    logParam.put("scoreType", 8);
                                    logParam.put("actionRemark", "完成下单赠送" + allScore + "积分");
                                    logParam.put("sendWx", sendWx);
                                    scoreActiveCacheDao.addLog(logParam);
                                }
                                if (2 == sendWx) {
                                    Map<String, Object> log = new HashMap<String, Object>();
                                    log.put("logId", UUID.randomUUID().toString());
                                    log.put("customerId", customerId);
                                    log.put("growthValue", allScore);
                                    log.put("growthType", 8);
                                    log.put("actionRemark", "完成下单赠送" + allScore + "成长值");
                                    vipCustomerLogDao.addGrowth(log);
                                }
                                stringRedisTemplate.opsForValue().decrement(key, (long)reduce);
//                                stringRedisTemplate.delete(key);
                            }
                        }
                    }
                }
            }
        }
    }


    private void doScoreTask() {
        //获取所有的机构
        List<Map<String, Object>> tokenList = wxDao.getWxPublistList();
        for (Map<String, Object> tokenMap : tokenList) {
            String orgId = tokenMap.get("orgId").toString();
            List<Map<String, Object>> scoreRulesList = scoreActDao.getScoreActAllList(orgId);

            //如果规则是评论或者是点赞
            String redisKey = ARTICLE_BEHAVIOR + orgId + "*";
            Set<String> keys = stringRedisTemplate.keys(redisKey);
            for (String key : keys) {
                Long giveCount = Long.valueOf(stringRedisTemplate.opsForValue().get(key));
                //如果大于
                Long avgeNum = 0L;
                Long addSorce = 0L;
                Long subtractScore = 0L;
                String integralFieldName = "";
                //类型 grow 成长值 integral 积分
                String socreType = key.split("_")[4].split(":")[0];
                String bType = key.split("_")[3];
                //用户ID
                String customerId = key.split(":")[1];

                //成长值
                for (Map<String, Object> scoreRuleMap : scoreRulesList) {
                    Map<String, Object> rule = (Map<String, Object>) JSON.parse(scoreRuleMap.get("rule").toString());
                    int score = Integer.valueOf(rule.get("val2").toString());
                    int count = Integer.valueOf(rule.get("val1").toString());
                    avgeNum = giveCount / count;
                    if (avgeNum > 0) {
                        addSorce = avgeNum * score;
                        subtractScore = avgeNum * count;
                        String remark = bType.equals("givestar") ? "文章点赞赠送" + addSorce : "文章评论赠送" + addSorce;
                        Integer scoreType = bType.equals("givestar") ? CustomerScoreLog.ScoreType.LIKE.getType() : CustomerScoreLog.ScoreType.COMMENT.getType();
                        if (scoreRuleMap.get("type").equals("2") && socreType.equals("grow")) {
                            integralFieldName = IntegralEnums.customerGrowthScore.toString();
                            Map<String, Object> glog = new HashMap<>();
                            glog.put("logId", UUID.randomUUID().toString());
                            glog.put("customerId", customerId);
                            glog.put("growthValue", addSorce);
                            glog.put("growthType", scoreType);
                            glog.put("actionRemark", remark + "成长值");
                            vipCustomerLogDao.addGrowth(glog);
                            this.customerIntegralService.addIntegralCustomerLog(customerId, remark, integralFieldName, addSorce.toString(), IntegralEnums.contentSystem.toString(), orgId);
                            stringRedisTemplate.opsForValue().decrement(key, subtractScore);
                            break;
                        } else if (scoreRuleMap.get("type").equals("1") && socreType.equals("integral")) {
                            //积分
                            integralFieldName = IntegralEnums.customerScore.toString();
                            Map<String, Object> logParam = new HashMap<>();
                            logParam.put("scoreLogId", UUID.randomUUID().toString());
                            logParam.put("customerId", customerId);
                            logParam.put("scoreValue", addSorce);
                            logParam.put("scoreType", scoreType);
                            logParam.put("actionRemark", remark + "积分");
                            logParam.put("sendWx", 0);
                            scoreActiveCacheDao.addLog(logParam);
                            this.customerIntegralService.addIntegralCustomerLog(customerId, remark, integralFieldName, addSorce.toString(), IntegralEnums.contentSystem.toString(), orgId);
                            stringRedisTemplate.opsForValue().decrement(key, subtractScore);
                            break;
                        }
                    }
                }
            }
        }
    }




    //积分、成长值任务
    private void invokeScore(){
//        Set<String> contentAction = stringRedisTemplate.opsForSet().members("contentAction");
//        if (contentAction != null && !contentAction.isEmpty()) {
//            for(String ca:contentAction){
//                ContentAction contentActionTmp = JSON.parseObject(ca,ContentAction.class);
//                syncContentDao.addContentActionFromMq(contentActionTmp);
//            }
//        }
        List<Map<String, Object>> scoreRulesList = scoreActDao.getScoreAllList();
        if(null!=scoreRulesList && scoreRulesList.size()>0){
            for(Map<String, Object> sc:scoreRulesList){
                Map<String,Object> rule = (Map<String,Object>)JSON.parse(sc.get("rule").toString());
                int val1 = Integer.valueOf(rule.get("val1").toString());
                int val2 = Integer.valueOf(rule.get("val2").toString());
                String orgId = sc.get("orgId").toString();
                String activeType = sc.get("activeType").toString();
                String remark = "";
                int actType = 0;
                if("share".equals(activeType)){
                    remark="文章分享赠送";
                    actType = 2;
                }
                if("comment".equals(activeType)){
                    remark="文章评论赠送";
                    actType = 3;
                }
                if("givestar".equals(activeType)){
                    remark="文章点赞赠送";
                    actType = 1;
                }
                String type = sc.get("type").toString();
                String integralFieldName;
                String scoreType;
                int sendWx;
                if("1".equals(type)){
                    //积分
                    scoreType = "integral";
                    integralFieldName = IntegralEnums.customerScore.toString();
                    sendWx = 1;
                }else{
                    //成长值
                    scoreType = "growth";
                    integralFieldName = IntegralEnums.customerGrowthScore.toString();
                    sendWx = 2;
                }
                String rKeys = ARTICLE_BEHAVIOR + orgId + "_" + activeType + "_" + scoreType + ":*";
                Set<String> keys = stringRedisTemplate.keys(rKeys);
                if(null!=keys && keys.size()>0){
                    for(String key:keys){
                        String[] split = key.split(":");
                        String customerId = split[1];
                        String numStr = stringRedisTemplate.opsForValue().get(key);
                        int num = Integer.valueOf(numStr==null?"0":numStr);
                        Integer score = 0;
                        if(num>=val1){
                            score = (num/val1)*val2;
                            int reduce = val1;
                            if(val1>0){
                                reduce = num-(num%val1);
                            }
                            this.customerIntegralService.addIntegralCustomerLog(customerId,remark, integralFieldName,score.toString(),IntegralEnums.contentSystem.toString(),orgId);
                            if(1==sendWx){
                                Map<String,Object> logParam = new HashMap<>();
                                logParam.put("scoreLogId", UUID.randomUUID().toString());
                                logParam.put("customerId", customerId);
                                logParam.put("scoreValue", score);
                                logParam.put("scoreType", actType);
                                logParam.put("actionRemark", remark+score+"积分");
                                logParam.put("sendWx", sendWx);
                                scoreActiveCacheDao.addLog(logParam);
                            }
                            if(2==sendWx){
                                Map<String, Object> log = new HashMap<String, Object>();
                                log.put("logId", UUID.randomUUID().toString());
                                log.put("customerId", customerId);
                                log.put("growthValue", score);
                                log.put("growthType", actType);
                                log.put("actionRemark", remark+score+"成长值");
                                vipCustomerLogDao.addGrowth(log);
                            }
                            stringRedisTemplate.opsForValue().decrement(key, (long)reduce);
                        }
                    }
                }
            }
        }
    }

    //成长值任务
    private void invokeGrowthScore(String day){
        // 获取积分规则
        SimpleDateFormat format = new SimpleDateFormat(CalendarUtils.DAY_FORMAT);
        String yesterday;
        if (!StringUtils.isEmpty(day)) {
            yesterday = day;
        } else {
            yesterday = format.format(CalendarUtils.getYesterdayDefault());
        }
        List<ScoreAct> scoreRules = scoreActDao.listScoreActAll("2");

        Map<String, List<ShareArticleLog>> orgData = new HashMap<>();
        List<Customer> updateCustomers = new ArrayList<>();
        List<CustomerScoreLog> scoreLogs = new ArrayList<>();
        for (ScoreAct scoreRule : scoreRules) {
            String ruleJson = scoreRule.getRule();
            String ruleType = scoreRule.getActiveType();
            String orgId = scoreRule.getOrgId();
            if (StringUtils.isEmpty(orgId) || StringUtils.isEmpty(ruleJson)) {
                continue;
            }

            RuleValue rule = JSON.parseObject(ruleJson, RuleValue.class);
            int count = Integer.parseInt(rule.getVal1());
            int score = Integer.parseInt(rule.getVal2());

            List<ShareArticleLog> articleLogs = orgData.get(orgId);
            if (articleLogs == null) {
                // 昨日传播数据
                articleLogs = articleDataDao.listLogByOrgId(orgId, yesterday);
                orgData.put(orgId, articleLogs);
            }

            LOGGER.info("<----成长值结算任务---->scoreRule:"+JSON.toJSONString(scoreRule));
            LOGGER.info("<----成长值结算任务---->articleLogs:"+JSON.toJSONString(articleLogs));

            for (ShareArticleLog log : articleLogs) {
                int addScore = 0;
                int scoreLogType;
                String remark = "";
                String sourceFieldName = "";
                switch (ruleType) {
                    case "share":
                        addScore += ((log.getPeopleAmount()/count)*score);
                        scoreLogType = CustomerScoreLog.ScoreType.SHARE.getType();
                        remark = "转发分享赠送" + addScore;
                        sourceFieldName = IntegralEnums.contentSystem.toString();
                        break;
                    case "givestar":
                        addScore += ((log.getLikeAmount()/count)*score);
                        scoreLogType = CustomerScoreLog.ScoreType.LIKE.getType();
                        remark = "文章点赞赠送" + addScore;
                        sourceFieldName = IntegralEnums.contentSystem.toString();
                        break;
                    case "comment":
                        addScore += ((log.getCommentAmount()/count)*score);
                        scoreLogType = CustomerScoreLog.ScoreType.COMMENT.getType();
                        remark = "文章评论赠送" + addScore;
                        sourceFieldName = IntegralEnums.contentSystem.toString();
                        break;
//                    case "order":
//                        addScore += ((log.getOrderNum()/count)*score);
//                        scoreLogType = CustomerScoreLog.ScoreType.ORDER.getType();
//                        remark = "完成下单赠送成长值" + addScore;
//                        sourceFieldName = IntegralEnums.mallSystem.toString();
//                        break;
                    default: continue;
                }
                if (addScore <= 0) {
                    continue;
                }
                Customer customer = new Customer();
                customer.setCustomerScore(addScore + 0L);
                customer.setCustomerId(log.getCustomerId());
                customer.setOrgId(orgId);
                customer.setCreateUser(remark);
                customer.setParentShareWay(sourceFieldName);
                updateCustomers.add(customer);

                CustomerScoreLog scoreLog = new CustomerScoreLog(
                        UUID.randomUUID().toString(), log.getCustomerId(), addScore + 0L,null,null,
                        scoreLogType, null,remark
                );
                scoreLogs.add(scoreLog);
            }
        }

        // 更新用户成长值
        if (updateCustomers.size() > 0 && scoreLogs.size() > 0) {
            for(Customer cu:updateCustomers){
                this.customerIntegralService.addIntegralCustomerLog(cu.getCustomerId(),cu.getCreateUser(), IntegralEnums.customerGrowthScore.toString(),cu.getCustomerScore().toString(),cu.getParentShareWay(),cu.getOrgId());
            }
//            articleDataDao.updateCustomerScoreBatch(updateCustomers);
            articleDataDao.insertCustomerScoreLogBatch(scoreLogs);
        }
    }

    @Setter
    @Getter
    static class RuleValue{
        private String val1;
        private String val2;
    }
}

